#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <netdb.h>            // struct addrinfo
#include <arpa/inet.h>
#include "esp_netif.h"
#include "esp_log.h"
#include "Drivers/tcp_drv.h"
#include "cJSON.h"
#include "App/ota_task.h"

#define TAG "TCP"

static void depkt_json(char *s);
static Socket_t sock;
static uint8_t g_url[512] = {0};
SemaphoreHandle_t xSemTcpRecvNone = NULL;

void TCP_Recv_Task(void *param)
{
    char rx_buffer[512];
    int len = 0;
    while(1)
    {
        len = recv(sock, rx_buffer, sizeof(rx_buffer), 0);
        if (len < 0)
        {
            ESP_LOGE(TAG, "recv failed: errno %d", errno);

            // xEventGroupSetBits(OTAEventGroup, OTA_FINISH_BIT);
            xSemaphoreGive(xSemTcpRecvNone);
            shutdown(sock, 0);
            close(sock);
            vTaskDelete(NULL);
        }
        else 
        {
            ESP_LOGI(TAG, "Received %d bytes: %.*s", len, len, rx_buffer);
            if(!strstr(rx_buffer, "NONE"))          //接收到的数据不带NONE就是升级
            {
                depkt_json(rx_buffer);
                // if(isMyUpdate)/***********驱动层不应该直接调用业务层代码***********/
                //     xEventGroupSetBits(OTAEventGroup, OTA_START_BIT);           
                // else
                //     xEventGroupSetBits(OTAEventGroup, OTA_STC_DOWLOAD_BIT);
            }
            else
            {
                // if(isMyUpdate)
                //     xEventGroupSetBits(OTAEventGroup, OTA_FINISH_BIT);
                // else
                //     xEventGroupSetBits(OTAEventGroup, OTA_STC_FINISH_BIT);
                g_url[0] = '\0';
                xSemaphoreGive(xSemTcpRecvNone);
            }
            if(!isMyUpdate)
            {
                Disconnect_TCP(); break;
            }
               
        }

        vTaskDelay(50 / portTICK_PERIOD_MS);
    }
    ESP_LOGI(TAG, "TCP receive task exit");
    vTaskDelete(NULL);
}

esp_err_t TCP_Connect(void)
{
    char host_ip[IP_MAX_LEN];
    int addr_family = AF_INET;
    int ip_protocol = IPPROTO_IP;
    xSemTcpRecvNone = xSemaphoreCreateBinary();
    struct sockaddr_in dest_addr = 
    {
        .sin_family = AF_INET,
        .sin_port = htons(TCP_PORT)
    };

    struct addrinfo *result;  
    if(getaddrinfo(TCP_DOMAIN, TCP_PORT_STR, NULL, &result) != 0)
    {
        ESP_LOGE(TAG, "getaddrinfo failed");
        strcpy(host_ip,TCP_IP);         //失败使用固定IP
    }
    else
    {
        ESP_LOGI(TAG, "getaddrinfo success");
        
        struct sockaddr_in *ipv4 = NULL;

        if (result->ai_family == AF_INET)
        {
            ipv4 = (struct sockaddr_in *)result->ai_addr;
            inet_ntop(result->ai_family, &ipv4->sin_addr, host_ip, sizeof(host_ip));
        }
        
    }
    freeaddrinfo(result);
    
    inet_pton(AF_INET, host_ip, &dest_addr.sin_addr);           // 将点分十进制的 IP 地址转换为二进制形式，并存储到 dest_addr 结构体中

    sock =  socket(addr_family, SOCK_STREAM, ip_protocol);

    if (sock < 0) 
    {    ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
        return ESP_FAIL;
    }

    ESP_LOGI(TAG, "Socket created, connecting to %s", host_ip);

    int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));

    if (err != 0) 
    {
        ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
        return ESP_FAIL;
    }

    ESP_LOGI(TAG, "Successfully connected");
    xTaskCreate(TCP_Recv_Task, "tcp_recv_task", 4096, NULL, 10, NULL);
    return ESP_OK;
}

esp_err_t TCP_Send(uint8_t *data, int len)
{
    int err = send(sock, data, len, 0);
    ESP_LOGI(TAG, "Send %d bytes", len);
    if (err < 0) 
    {
        ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
        err = ESP_FAIL;
    }else
        err = ESP_OK;
        
    return err;
}


static void depkt_json(char *s)
{
    cJSON *pJsonRoot = cJSON_Parse(s + 23); // 过滤FILES_UPDATE_CHECK OLD

    if (pJsonRoot != NULL)
    {
        cJSON *urls = cJSON_GetObjectItem(pJsonRoot, "urls");       // 解析info字段数组内容

        cJSON *pInfoItem = NULL;
        cJSON *pUrl = NULL;

        if (!urls)
            goto file_fail;
        else
        {
            int arryLength = cJSON_GetArraySize(urls); // 获取数组长度
            int i;
            for (i = 0; i < arryLength; i++)
            {
                pInfoItem = cJSON_GetArrayItem(urls, i); // 获取数组中JSON对象
                if (NULL != pInfoItem)
                {

                    pUrl = cJSON_GetObjectItem(pInfoItem, "url"); // 解析relay字段字符串内容
                    if (pUrl)
                    {
                        strcpy((char *)g_url, pUrl->valuestring); // 拷贝内容到字符串数组
                        g_url[strlen(pUrl->valuestring)] = '\0';
                        
                        ESP_LOGI(TAG, "url = %s", g_url);
                        // return true;
                    }
                }
            }
        }
    }
file_fail:
    // return false;
    cJSON_Delete(pJsonRoot); 
}

uint8_t *GetUrl(void)
{
    return g_url;
}

void Disconnect_TCP(void)
{
    ESP_LOGI(TAG, "Disconnect");
    shutdown(sock, 0);
    close(sock);
}